<template>
    <el-table
        :id="tableId"
        class="data-table"
        ref="dataTable"
        :height="baseTableHeight"
        :data="tableData"
        v-loading="tableConfig.loading"
        :border="tableConfig.border !== undefined ? tableConfig.border : false"
        :stripe="tableConfig.stripe !== undefined ? tableConfig.stripe : false"
        :row-key="tableConfig.rowKey || undefined"
        :size="tableConfig.size | setSize(tableConfig.size)"
        :tree-props="tableConfig.treeProps || undefined"
        :highlight-current-row="tableConfig.highlightCurrentRow || false"
        :default-expand-all="tableDefaultExpandAll"
        :row-class-name="tableRowClassName"
        @current-change="handleCurrentChange"
        @selection-change="handleSelectionChange"
        @expand-change="handelExpandChange"
    >
        <template v-for="(column, index) in tableHeader">
            <template v-if="column.children && column.children.length > 0">
                <template v-if="column.visible">
                    <el-table-column
                        :key="'first-child-' + index"
                        :label="column.label || ''"
                        :width="column.width || undefined"
                        :minWidth="column.minWidth || undefined"
                        :align="column.align || 'center'"
                        :fixed="column.fixed || undefined"
                        :show-overflow-tooltip="column.showOverflowTooltip"
                    >
                        <table-column
                            v-for="(item, idx) in column.children"
                            :key="idx"
                            :columnData="item"
                        >
                            <template slot-scope="scope">
                                <slot :scope="handledScope(scope)"></slot>
                            </template>
                        </table-column>
                    </el-table-column>
                </template>
            </template>
            <template v-else-if="column.type && column.type === 'selection'">
                <el-table-column
                    v-if="column.visible"
                    type="selection"
                    :key="'selection' + index"
                    :width="column.width || undefined"
                    :minWidth="column.minWidth || undefined"
                    :align="column.align || 'center'"
                    :fixed="column.fixed || undefined"
                    :reserve-selection="column.reserveSelection || undefined"
                />
            </template>
            <template v-else-if="column.type && column.type !== 'selection'">
                <table-column
                    v-if="column.visible"
                    :key="'first-child-' + index"
                    :columnData="column"
                >
                    <template slot-scope="scope">
                        <slot :scope="handledScope(scope)"></slot>
                    </template>
                </table-column>
            </template>
            <template v-else>
                <el-table-column
                    v-if="column.visible"
                    :key="'first-child-' + column.prop"
                    :prop="column.prop"
                    :label="column.label || ''"
                    :width="column.width || undefined"
                    :minWidth="column.minWidth || undefined"
                    :align="column.align || 'center'"
                    :fixed="column.fixed || undefined"
                    :show-overflow-tooltip="column.showOverflowTooltip"
                />
            </template>
        </template>
    </el-table>
</template>

<script>
import tableColumn from './components/tableColumn.vue'
import { getUuid } from '@/utils/tool.js'
export default {
    name: 'BaseTable',
    components: {
        /**
         * 表格column子组件
         */
        tableColumn
    },
    watch: {
        /**
         * 监听表格数据 一旦变化 表格重新布局 并设置默认选中
         */
        tableData: {
            handler() {
                this.doLayout()
                this.setDefaultSelection()
            },
            immediate: true,
            deep: true
        },
        /**
         * 监听表头数据 一旦变化 表格重新布局
         */
        tableHeader: {
            handler() {
                this.doLayout()
            },
            immediate: true,
            deep: true
        },
        'tableConfig.defaultExpandAll': {
            handler: function(newVal) {
                this.tableDefaultExpandAll = newVal
            },
            immediate: true
        }
    },
    props: {
        /**
         * 表格数据(必传)
         * @type Array
         * @value Array
         */
        tableData: {
            type: Array,
            required: true,
            default: () => []
        },
        /**
         * 表头数据数据(必传)
         * @type Array
         * @value Array
         */
        tableHeader: {
            type: Array,
            required: true,
            default: () => []
        },
        /**
         * 表格其余所有配置项
         * @type Object
         * @value {}
         */
        tableConfig: {
            type: Object,
            required: false,
            default: () => {
                return {
                    /**
                     * 表格是否带有纵向边框
                     * @type Boolean/String
                     * @value Boolean/String
                     */
                    border: false,
                    /**
                     * 尺寸
                     * @type String
                     * @value 	medium / small / mini
                     */
                    size: '',
                    /**
                     * 表格是否带有斑马纹
                     * @type Boolean/String
                     * @value Boolean/String
                     */
                    stripe: false,
                    /**
                     * 行数据的 Key，用来优化 Table 的渲染；用于判断表格行数据唯一性的标识字段；
                     * 当需要指定表格多选默认选中、单选选中、树形结构表格时 需要用到此属性
                     * 默认值为 id
                     * @type String
                     * @value String
                     */
                    rowKey: 'id',
                    /**
                     * 表格多选情况下默认选中的key集合
                     * 默认的key字段为id 可以通过传rowKey指定
                     * @type Array
                     * @value Array
                     */
                    defaultSelectionKeys: [],
                    /**
                     * 渲染树形表格的配置选项
                     * @type Object
                     * @value { hasChildren: 'hasChildren', children: 'children' }
                     */
                    treeProps: {
                        hasChildren: 'hasChildren',
                        children: 'children'
                    },
                    /**
                     * 是否要高亮当前行
                     * 设置为true即表示开启表格单击选中模式
                     * @type Boolean, String
                     * @value Boolean, String
                     */
                    highlightCurrentRow: false,
                    /**
                     * 表格加载效果
                     */
                    loading: false,
                    /**
                     * 是否展开所有行
                     * 树表时生效
                     */
                    defaultExpandAll: false,
                    /**
                     * 表格的默认高度
                     */
                    height: ''
                }
            }
        }
    },
    data() {
        return {
            multipleSelection: [], // 选中的行数据
            tableDefaultExpandAll: false, // 是否展开所有行
            baseTableHeight: 0, // 表格高度
            tableId: getUuid()
        }
    },
    methods: {
        /**
         * 对表格进行重新布局
         */
        doLayout() {
            this.$nextTick(() => {
                if (this.tableConfig.height) {
                    if (this.tableConfig.height === 'auto') {
                        this.baseTableHeight = 0
                        const tableId = document.getElementById(this.tableId)
                        tableId.style.overflow = 'hidden'
                        let temp = tableId.getElementsByClassName(
                            'el-table__row'
                        )
                        let theader = tableId.getElementsByTagName('thead')[0]
                        this.baseTableHeight = theader.scrollHeight + 2
                        if (temp.length > 0) {
                            for (let i = 0; i < temp.length; i++) {
                                const item = temp[i]
                                this.baseTableHeight += item.scrollHeight
                            }
                        } else {
                            this.baseTableHeight += 100
                        }
                    } else {
                        this.baseTableHeight = '100%'
                    }
                } else {
                    this.baseTableHeight = '100%'
                }
                this.$refs.dataTable.doLayout()
            })
        },
        /**
         * 对作用域插槽数据处理
         * 取出多层嵌套数据中的最里面一层数据 便于开发人员取到数据
         * @params 下一级组件中绑定的作用域插槽数据
         */
        handledScope(scope) {
            while (
                scope.scope &&
                Object.prototype.toString.call(scope.scope) ===
                    '[object Object]'
            ) {
                scope = scope.scope
            }
            return scope || {}
        },
        /**
         * 表格多选数据发生改变时调用 将多选数据返回给父组件
         * @params 表格实时选中的数据
         * @type Array
         */
        handleSelectionChange(val) {
            this.multipleSelection = val
            this.$emit('handleSelection', this.multipleSelection)
        },
        /**
         * 表格单机选中某行时调用 将当前选中行返回给父组件
         * @params 表格实时选中的数据 和之前选中的数据
         * @type Object
         */
        handleCurrentChange(row, oldCurrentRow) {
            if (this.tableConfig.highlightCurrentRow) {
                this.$emit('handleCurrentChange', row, oldCurrentRow)
            }
        },
        /**
         * 设置表格当前选中行 (可直接使用此方法设置表格高亮行)
         * @params 选中行的key （默认字段为id 可以用rowKey属性指定）
         * @type String/Number
         */
        setCurrentRow(val) {
            if (typeof val === 'string' || typeof val === 'number') {
                this.tableData.forEach(v => {
                    if (String(val) === String(v[this.tableConfig.rowKey])) {
                        this.$refs['dataTable'].setCurrentRow(v)
                    }
                })
            } else if (
                Object.prototype.toString.call(val) === '[object Object]'
            ) {
                this.$refs['dataTable'].setCurrentRow(val)
            }
        },
        /**
         * 设置表格多选选中
         * 通过defaultSelectionKeys属性判断（默认字段为id 可以用rowKey属性指定）
         */
        setDefaultSelection() {
            this.$nextTick(() => {
                if (
                    this.tableConfig.defaultSelectionKeys &&
                    this.tableConfig.defaultSelectionKeys.length
                ) {
                    this.tableData.forEach(v => {
                        if (
                            this.tableConfig.defaultSelectionKeys.indexOf(
                                v[this.tableConfig.rowKey]
                            ) >= 0
                        ) {
                            this.$refs['dataTable'].toggleRowSelection(v, true)
                        }
                    })
                }
            })
        },
        /**
         * 展开行被触发
         * @param {*} row
         * @param {*} rows
         */
        handelExpandChange(row, rows) {
            this.$emit('handleExpandChange', row, rows)
        },
        /**
         * 切换行展开
         */
        toggleRowExpansion() {
            this.tableDefaultExpandAll = !this.tableDefaultExpandAll
            this.toggleRowExpansionAll(
                this.tableData,
                this.tableDefaultExpandAll
            )
        },
        toggleRowExpansionAll(data, isExpansion) {
            data.forEach(item => {
                this.$refs.dataTable.toggleRowExpansion(item, isExpansion)
                if (item.children !== undefined && item.children !== null) {
                    this.toggleRowExpansionAll(item.children, isExpansion)
                }
            })
        },
        /**
         * 隐藏行
         */
        tableRowClassName(row) {
            if (row.row.delViews) {
                return 'hidden-row'
            }
            return ''
        },
        /**
         * 清空选中项
         */
        clearSelection() {
            this.$refs.dataTable.clearSelection()
        }
    }
}
</script>

<style lang="scss" scoped>
.data-table {
    width: 100%;
}
</style>
